package me.zhengjie.modules.web.service.pay.order;

import cn.hutool.core.thread.ThreadUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import me.zhengjie.config.exception.WeChatException;
import me.zhengjie.constant.ConstantUtils;
import me.zhengjie.modules.system.domain.*;
import me.zhengjie.modules.system.service.CourseInfoService;
import me.zhengjie.modules.system.service.CourseOrderService;
import me.zhengjie.modules.system.service.WxUserService;
import me.zhengjie.modules.system.service.dto.CourseOrderDto;
import me.zhengjie.modules.web.domain.pay.OrderSubmitRequest;
import me.zhengjie.modules.web.domain.pay.OrderSubmitResponse;
import me.zhengjie.modules.web.enums.ApplicantsSignStatusEnum;
import me.zhengjie.modules.web.enums.OrderStatusEnum;
import me.zhengjie.modules.web.service.course.ICourseService;
import me.zhengjie.modules.web.service.dis.IDisOrderWebService;
import me.zhengjie.modules.web.service.mybatisplus.ICourseApplicantsMainPlusService;
import me.zhengjie.modules.web.service.mybatisplus.ICourseApplicantsPlusService;
import me.zhengjie.modules.web.service.order.IOrderService;
import me.zhengjie.modules.web.service.pay.IOrderSubmitService;
import me.zhengjie.modules.weixin.utils.OrderUtil;
import me.zhengjie.request.ATMRContext;
import me.zhengjie.utils.DateUtil;
import me.zhengjie.utils.StringUtils;
import me.zhengjie.utils.enums.OrderPrefixEnum;
import me.zhengjie.utils.enums.OrderTypeEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;


@Service
public class CourseOrderSubmitServiceImpl implements IOrderSubmitService {
    @Autowired
    private CourseOrderService courseOrderService;

    @Autowired
    private CourseInfoService courseInfoService;

    @Autowired
    private ICourseService courseService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IDisOrderWebService disOrderWebService;

    @Autowired
    private ICourseApplicantsPlusService applicantsPlusService;

    @Autowired
    private ICourseApplicantsMainPlusService applicantsMainPlusService;

    @Autowired
    private WxUserService wxUserService;

    @Override
    public int orderType() {
        return OrderTypeEnum.Course.getOrderType();
    }

    @Override
    @Transactional
    public OrderSubmitResponse execute(OrderSubmitRequest request) {
        String courseNo = request.getCourseNo();
        if (StringUtils.isBlank(courseNo)){
            throw new WeChatException("缺少参数courseNo");
        }
        CourseInfo courseInfo = courseInfoService.getInfoByNo(courseNo);
        if (Objects.isNull(courseInfo)){
            throw new WeChatException("参数有误");
        }
        String orderSn = OrderUtil.GetOrderNumber(OrderPrefixEnum.Course.getPrefix());
        String openId = ATMRContext.getContext().getOpenId();
        if (StringUtils.isBlank(openId)){
            openId = request.getBackendOpenId();
        }
        int buyNumber = 1;
        List<OrderSubmitRequest.CourseApplicantsRequest> applicantsList = request.getApplicantsList();
        if (CollectionUtils.isNotEmpty(applicantsList)){
            if (applicantsList.stream().anyMatch(s -> StringUtils.isAnyBlank(s.getMobile(),s.getRealName()))){
                throw new WeChatException("报名人参数缺少");
            }
            if (applicantsList.stream().anyMatch(s -> !checkMobileWithRegex(s.getMobile()))){
                throw new WeChatException("手机号不合法");
            }
            LambdaQueryWrapper<CourseApplicants> removeWrapper = new LambdaQueryWrapper<>();
            removeWrapper.eq(CourseApplicants::getCourseNo,courseNo);
            removeWrapper.eq(CourseApplicants::getOpenId,openId);
            removeWrapper.eq(CourseApplicants::getPaid,ConstantUtils.Order_NoPay);
            applicantsPlusService.remove(removeWrapper);

            LambdaQueryWrapper<CourseApplicantsMain> removeMainWrapper = new LambdaQueryWrapper<>();
            removeMainWrapper.eq(CourseApplicantsMain::getCourseNo,courseNo);
            removeMainWrapper.eq(CourseApplicantsMain::getOpenId,openId);
            removeMainWrapper.eq(CourseApplicantsMain::getPaid,ConstantUtils.Order_NoPay);
            applicantsMainPlusService.remove(removeMainWrapper);

            List<CourseApplicants> list = new ArrayList<>();
            WxUser selfUser = null;
            for (OrderSubmitRequest.CourseApplicantsRequest s : applicantsList) {
                CourseApplicants applicants = new CourseApplicants();
                List<WxUser> wxUserList = wxUserService.findByMoblie(s.getMobile());
                if (CollectionUtils.isNotEmpty(wxUserList)){
                    WxUser wxUser = wxUserList.get(0);
                    applicants.setNickName(wxUser.getNickname());
                    applicants.setOneself(0);
                    if (wxUser.getOpenId().equals(openId)){
                        applicants.setOneself(1);
                        selfUser = wxUser;
                    }
                }
                applicants.setMobile(s.getMobile());
                applicants.setRealName(s.getRealName());
                applicants.setCourseNo(courseNo);
                applicants.setCourseName(courseInfo.getCourseName());
                applicants.setOrderNo(orderSn);
                applicants.setPaid(ConstantUtils.Order_NoPay);
                if (courseInfo.getSellPrice().compareTo(BigDecimal.ZERO) == 0 || request.isNotNeedPay()){
                    applicants.setPaid(ConstantUtils.Order_Payed);
                }
                applicants.setConsume(ConstantUtils.InValid);
                applicants.setSignStatus(ApplicantsSignStatusEnum.NotSign.getSignStatus());
                applicants.setOpenId(openId);
                applicants.setExpireTime(DateUtil.dateConvertTimestamp(DateUtil.addMonth(new Date(),24)));
                applicants.setReferee(request.getReferee());
                list.add(applicants);
            }
            try {
                if (CollectionUtils.isNotEmpty(list)){
                    applicantsPlusService.saveBatch(list);
                }
            } catch (Exception e) {
                throw new WeChatException("不可重复报名");
            }
            if (Objects.isNull(selfUser)){
                selfUser = wxUserService.findByOpenId(openId);
            }
            CourseApplicantsMain courseApplicantsMain = new CourseApplicantsMain();
            courseApplicantsMain.setCourseNo(courseNo);
            courseApplicantsMain.setCourseName(courseInfo.getCourseName());
            courseApplicantsMain.setOrderNo(orderSn);
            courseApplicantsMain.setOpenId(openId);
            courseApplicantsMain.setMobile(selfUser.getMobile());
            courseApplicantsMain.setNickName(selfUser.getNickname());
            courseApplicantsMain.setRealName(selfUser.getRealName());
            courseApplicantsMain.setCreateTime(DateUtil.TimestampNow());
            courseApplicantsMain.setPaid(ConstantUtils.Order_NoPay);
            courseApplicantsMain.setReferee(request.getReferee());
            if (courseInfo.getSellPrice().compareTo(BigDecimal.ZERO) == 0 || request.isNotNeedPay()){
                courseApplicantsMain.setPaid(ConstantUtils.Order_Payed);
            }
            applicantsMainPlusService.save(courseApplicantsMain);
            buyNumber = applicantsList.size();
        }
        BigDecimal sellPrice = courseInfo.getSellPrice().multiply(new BigDecimal(String.valueOf(buyNumber)));
        CourseOrder courseOrder = new CourseOrder();
        courseOrder.setOrderAmount(sellPrice);
        courseOrder.setOpenId(openId);
        courseOrder.setOrderNo(orderSn);
        courseOrder.setCreateTime(DateUtil.TimestampNow());
        courseOrder.setPayAmount(BigDecimal.ZERO);
        courseOrder.setPaySerialid("");
        courseOrder.setPrePayid("");
        courseOrder.setCourseNo(courseNo);
        courseOrder.setPayStatus(OrderStatusEnum.WaitingPay.getOrderStatus());
        courseOrder.setOrderStatus(OrderStatusEnum.WaitingPay.getOrderStatus());
        WxUser wxUser = wxUserService.findByOpenId(openId);
        courseOrder.setNickName(wxUser.getNickname());
        courseOrder.setRealName(wxUser.getRealName());
        if (sellPrice.compareTo(BigDecimal.ZERO) == 0 || request.isNotNeedPay()){
            courseOrder.setPayStatus(OrderStatusEnum.Payed.getOrderStatus());
            courseOrder.setOrderStatus(OrderStatusEnum.Payed.getOrderStatus());
            //支付成功自动加入班级
            String finalOpenId = openId;
            ThreadUtil.execAsync(() -> {
                courseService.autoJoinClass(finalOpenId,courseNo);
            });
            //更新报名人
            if (CollectionUtils.isNotEmpty(applicantsList)){
                CourseApplicants applicants = new CourseApplicants();
                applicants.setPaid(ConstantUtils.Order_Payed);
                LambdaQueryWrapper<CourseApplicants> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(CourseApplicants::getOrderNo,orderSn);
                applicantsPlusService.update(applicants,wrapper);

                CourseApplicantsMain applicantsMain = new CourseApplicantsMain();
                applicantsMain.setPaid(ConstantUtils.Order_Payed);
                LambdaQueryWrapper<CourseApplicantsMain> mainWrapper = new LambdaQueryWrapper<>();
                mainWrapper.eq(CourseApplicantsMain::getOrderNo,orderSn);
                applicantsMainPlusService.update(applicantsMain,mainWrapper);
            }
            //计算佣金
            /*DisOrderCalcDTO disOrderCalcDTO = new DisOrderCalcDTO();
            disOrderCalcDTO.setOrderSn(orderSn);
            disOrderCalcDTO.setOrderAmount(RandomUtil.randomBigDecimal(BigDecimal.TEN,BigDecimal.valueOf(1000)));
            disOrderCalcDTO.setOpenId(openId);
            disOrderCalcDTO.setOrderType(DisOrderType_Course);
            disOrderCalcDTO.setTitle(courseInfo.getCourseName());
            disOrderWebService.insertDisOrder(disOrderCalcDTO);*/
        }
        courseOrder.setCourseName(courseInfo.getCourseName());
        Timestamp timestamp = Timestamp.valueOf(LocalDateTime.now().plusMinutes(ConstantUtils.DefaultExpireTime));
        courseOrder.setExpireTime(timestamp);
        courseOrder.setRemark(request.getGrantFlag());
        CourseOrderDto examOrderDto = courseOrderService.create(courseOrder);
        OrderSubmitResponse response = new OrderSubmitResponse();
        response.setOrderId(examOrderDto.getOrderId());
        response.setOrderSn(orderSn);
        response.setOrderStatus(courseOrder.getOrderStatus());

        orderService.orderExpire2Redis(orderType(),orderSn,timestamp);
        return response;
    }

    /**
     * 通过正则判断手机号
     * @param mobile 手机号
     * @return
     */
    private boolean checkMobileWithRegex(String mobile){
        String pattern = "^1[\\d]{10}";
        boolean isMatch = Pattern.matches(pattern, mobile);
        return isMatch;
    }
}
